// 引入依赖
const express = require('express');
const crypto = require('crypto');
const axios = require('axios');

// 文件分片大小常量
const SHARD_SIZE = 10;

// 数据中心类
class DataCenter {
    constructor() {
        // 存储元数据
        this.metadata = new Map();
        // 存储节点
        this.nodes = ['http://localhost:3001', 'http://localhost:3002'];
        // 创建 Express 应用
        this.app = express();
        // 解析 json 数据
        this.app.use(express.json());
        // 挂载路由规则
        this.setupRoutes();
        console.log('数据中心初始化完成');
    }

    /**
     * 设置路由规则
     */
    setupRoutes() {
        // 文件上传
        this.app.post('/upload', async (req, res) => {
            // 接收文件信息
            const { filename, content } = req.body;

            // 创建文件哈希
            const fileHash = crypto.createHash('sha256').update(content).digest('hex');

            // 文件分片（每片10字节, 由于测试的数据量一般不大，所以这里直接10字节分片）
            const shards = [];
            for (let i = 0; i < content.length; i += SHARD_SIZE) {
                shards.push(content.slice(i, i + SHARD_SIZE));
            }

            // 分发分片到存储节点
            const shardInfo = [];
            for (let i = 0; i < shards.length; i++) {
                const shard = shards[i];
                const shardHash = crypto.createHash('sha256').update(shard).digest('hex');
                const node = this.nodes[i % this.nodes.length]; // 轮流选择节点

                try {
                    await axios.post(`${node}/store`, {
                        hash: shardHash,
                        content: shard
                    });
                    shardInfo.push({ index: i, hash: shardHash, node });
                } catch (error) {
                    console.error(`分片${i}存储失败: ${error.message}`);
                }
            }

            // 保存元数据
            this.metadata.set(filename, {
                fileHash,
                shardInfo
            });

            res.json({
                success: true,
                filename,
                shardCount: shards.length,
                fileHash
            });
        });

        // 文件下载
        this.app.get('/download/:filename', async (req, res) => {
            const filename = req.params.filename;
            const fileMeta = this.metadata.get(filename);

            if (!fileMeta) {
                return res.status(404).json({ error: '文件不存在' });
            }

            try {
                // 从各节点获取分片
                const shardPromises = fileMeta.shardInfo.map(async ({ node, hash }) => {
                    const response = await axios.get(`${node}/retrieve?hash=${hash}`);
                    return response.data.content;
                });

                const shardContents = await Promise.all(shardPromises);

                // 重新组合文件
                const fileContent = shardContents.join('');
                const downloadedHash = crypto.createHash('sha256').update(fileContent).digest('hex');

                // 验证文件完整性
                if (downloadedHash !== fileMeta.fileHash) {
                    return res.status(500).json({ error: '文件损坏，哈希不匹配' });
                }

                res.json({
                    filename,
                    content: fileContent,
                    length: fileContent.length
                });
            } catch (error) {
                res.status(500).json({ error: `下载失败: ${error.message}` });
            }
        });

        // 查看元数据
        this.app.get('/metadata', (req, res) => {
            res.json({
                fileCount: this.metadata.size,
                files: Array.from(this.metadata.keys())
            });
        });
    }

    start(port = 3000) {
        this.app.listen(port, () => {
            console.log(`数据中心运行在 http://localhost:${port}`);
        });
    }
}

// 启动数据中心
const dataCenter = new DataCenter();
dataCenter.start();